#include <iostream>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
using namespace std;

#define NUM 1024 // 读取的字符串长度
#define SPACE " "

char command_line[NUM];
char *command_args[NUM];

/* Shell 内置函数: 路径跳转 */
int ChangeDir(const char *new_path)
{
    chdir(new_path);

    return 0; // 调用成功
}

int main()
{
    while (1)
    {
        // 1.显示提示符
        cout << "[csj@VM-16-11-ubuntu:]# ";
        fflush(stdout);

        // 2.获取输入的字符串
        memset(command_line, '\0', sizeof(command_line));
        fgets(command_line, NUM, stdin);
        // fgets默认会将键盘最后输入的回车，也就是\n读取走
        command_line[strlen(command_line) - 1] = '\0';

        // 3.将获取的字符串给分割开来
        command_args[0] = strtok(command_line, SPACE);
        int ret = 1;
        // 添加颜色
        if (strcmp(command_args[0] /* 程序名 */, "ls") == 0)
        {
            command_args[ret++] = (char *)"--color=auto";
        }
        while (command_args[ret++] = strtok(NULL, SPACE))
            ;

        // 4.判断是否是内建命令
        if (strcmp(command_args[0], "cd") == 0 && command_args[1] != NULL)
        {
            ChangeDir(command_args[1]); // 让调用方进行路径切换
            continue;
        }

        // 5.创建子进程进程序替换
        pid_t id = fork();
        if (id == 0)
        {
            // child
            execvp(command_args[0], command_args);
            exit(1); // 走到这里，说明程序替换失败了
        }
        int status = 0;
        pid_t r = waitpid(id, &status, 0);

        if (r > 0)
        {
            // status & 0x7F ----- sig
            // (status >> 8) & 0xFF ----- exit
            cout << "等待成功, sig: " << WTERMSIG(status);
            cout << ", exit: " << WEXITSTATUS(status) << endl;
        }
    }
    return 0;
}